package tictacstego;

/**
 * Project 4 -- TTTBoard
 * 
 * This class implements a Board for Tic-Tac-Toe
 * that keeps track of the current board state,
 * available moves, the current player, 
 * and the last move made.
 * 
 * @date Put the date you completed the class here.
 * 
 */


import java.util.LinkedList;

import interfaces.GameBoard;



public class TTTBoard implements GameBoard {
	// THE CURRENT BOARD STATE
	// declare an instance variable to store the current board state
	private char[][] board;
	// THE LIST OF AVAILABLE MOVES
	// declare an instance variable to store the list of available moves
	private LinkedList<String> availableMoves;
	// THE CURRENT PLAYER ID
	// declare an instance variable to store the current player ID
	private int currentPlayer;
	// THE LAST MOVE MADE
	// declare an instance variable to store the last move made
	private String lastMove;
	/**
	 * Construct a new TTTBoard
	 */
	public TTTBoard() {
		// initialize the current board state as a 3x3 char array with ' ' in every cell
	    board = new char[][] {{' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}};
		// initialize the list of available moves as a LinkedList
	    availableMoves = new LinkedList<String>();
		// add all legal moves to the list of available moves
	    for (int i = 0; i < 3; ++i) {
	        for (int j = 0; j < 3; ++j) {
	            int[] wtf = new int[] {i, j};
	            availableMoves.add(toMove(wtf));
	        }
	    }
		// set the current player to be the first player
	    currentPlayer = 1;
		// set the last move made to be null
	    lastMove = null;
	}
	
	/**
	 * Copy constructor for TTTBoards
	 * @param b - TTTBoard to be copied
	 */
	public TTTBoard(TTTBoard b) {
		// initialize the current board state as a 3x3 char array
	    board = new char[3][3];
		// initialize the list of available moves as a LinkedList
	    availableMoves = new LinkedList<String>();
		// set the current player to be the first player
	    currentPlayer = 1;
		// get a copy of the current board state from the given board
		// for each cell on the board
	    for (int i = 0; i < 3; ++i) {
	        for (int j = 0; j < 3; ++j) {
		//   copy the value of the cell
	            board[i][j] = b.board[i][j];
		//   if the cell is not empty
	            if (board[i][j] != ' ') {
	                //     update the current player
	                if (currentPlayer == 1)
	                    currentPlayer = 2;
	                else
	                    currentPlayer = 1;
	            } else {
	                //   else
	                //     add the cell to the list of available moves
	                int[] wtf = new int[] {i, j};
	                availableMoves.add(toMove(wtf));
	            }

	        }
	    }
		// set the last move to be the same as the given board's
	    lastMove = b.lastMove;
	}
	
	@Override
	public char[][] getBoard() {
		// return the current board state
		return board; // replace with your own return statement
	}

	@Override
	public boolean playMove(String move, int player) {
		// convert the move string to array indices
	    int[] moveIndices = toIndices(move);
		// if the cell is not open or the board is in a win state
	    if (board[moveIndices[0]][moveIndices[1]] != ' ' || hasWin())
		//   return false
	        return false;
	    
		// if the player id is 1
	    if (player == 1)
		//   place an 'X' in the cell
	        board[moveIndices[0]][moveIndices[1]] = 'X';
		// else
	    else
		//   place an 'O' in the cell
	        board[moveIndices[0]][moveIndices[1]] = 'O';
		// update the list of available moves
	    availableMoves.remove(move);
		// update current player id
	    currentPlayer = player == 1 ? 2 : 1;
		// update lastMove
	    lastMove = move;
		// return true
		return true; // replace with your own return statement
	}
	
	@Override
	public boolean playMove(String move) {
		// play the move with the current player's id
		// return true if the move was valid, false otherwise
		return playMove(move, currentPlayer); // replace with your own return statement
	}

	@Override
	public String[] getAvailableMoves() {
		// return the list of available moves as an array
	    LinkedList<String> retList = new LinkedList<String>();
	    for (int i = 0; i < 3; ++i) {
	        for (int  j = 0; j < 3; ++j) {
	            if (board[i][j] == ' ') {
	                int[] wtf = new int[] {i, j};
	                retList.add(toMove(wtf));
	            }
	        }
	    }
	    
	    String[] ret = new String[retList.size()];
	    retList.toArray(ret);
		return ret; // replace with your own return statement
	}
	
	@Override
	public boolean hasWin() {
		// return true if there exists a row, column, or diagonal 
		//   which has all 3 symbols the same, 
		//   and the symbols are not ' '
		// otherwise, return false;
	    for (int i = 0; i < 3; ++i) {
	        if (board[i][0] == board[i][1] && board[i][0] == board[i][2])
	            if (board[i][0] != ' ')
	                return true;
	    }
	    
	    for (int i = 0; i < 3; ++i) {
	        if (board[0][i] == board[1][i] && board[0][i] == board[2][i])
	            if (board[0][i] != ' ')
	                return true;
	    }
	    
	    if (board[0][0] == board[1][1] && board[0][0] == board[2][2])
	        if (board[0][0] != ' ')
	            return true;
	    
	    if (board[0][2] == board[1][1] && board[0][2] == board[2][0])
	        if (board[0][2] != ' ')
	            return true;
	    
		return false; // replace with your own return statement
	}
	
	@Override
	public boolean hasDraw() {
		// return true if there are no available moves 
		//   and the board is not in a winning configuration
		// otherwise, return false
	    if (hasWin())
	        return false;
	    if (getAvailableMoves().length == 0)
	        return true;
		return false; // replace with your own return statement
	}
	
	@Override
	public int getCurrentPlayer() {
		// return the current player's id
	    return currentPlayer; // replace with your own return statement
	}
	
	/* 
	 * Pretty-printed board looks like:
	 * (this is just an example)
	 *   0   1   2 
	 * A X | O |
	 *  ---+---+---
	 * B   |   |
	 *  ---+---+---
	 * C   | X |  
	 */
	@Override
	public String toString() {
		// build a string which contains the pretty-printed current board state
	    String ret = new String();
	    ret += "  0   1   2 \n";
	    ret += String.format("A %s | %s | %s \n", board[0][0], board[0][1], board[0][2]);
	    ret += " ---+---+---\n";
	    ret += String.format("B %s | %s | %s \n", board[1][0], board[1][1], board[1][2]);
	    ret += " ---+---+---\n";
	    ret += String.format("C %s | %s | %s \n", board[2][0], board[2][1], board[2][2]);
		return ret; // replace with your own return statement
	}

	@Override
	public String getLastMove() {
		// return the last move made on the board
		return lastMove; // replace with your own return statement
	}
	
	@Override
	public String toMove(int[] idx) {
		// convert the array indices to a move string
		// return the move string
	    String ret = new String();
	    ret += (char)(idx[0] + 'A');
	    ret += (char)(idx[1] + '0');
		return ret; // replace with your own return statement
	}
	
	@Override
	public int[] toIndices(String move) {
		// convert the move string to array indices
		// return the array indices
	    int row = move.charAt(0) - 'A';
	    int col = move.charAt(1) - '0';
		return new int[] {row, col}; // replace with your own return statement
	}
	
}
